
use std::sync::{Arc, Mutex};
use std::collections::HashMap;
use chrono::prelude::*;

pub trait SessionStore {
    fn init() -> Self;
    fn insert(&mut self, k: String, v: i64) -> Option<i64>;
    fn get(&self, k: &str) -> Option<i64>;
    fn delete(&mut self, k: &str) -> Option<i64>;
    fn clear_expired(&mut self);
}

#[derive(Clone)]
pub struct MemorySession {
    pub session: Arc<Mutex<HashMap<String, i64>>>,
}

impl SessionStore for MemorySession {

    fn init() -> Self {
        MemorySession { session: Arc::new(Mutex::new(HashMap::new())) }
    }

    fn insert(&mut self, k: String, v: i64) -> Option<i64> {
        let mut data = self.session.lock().unwrap();
        data.insert(k, v)
    }

    fn get(&self, k: &str) -> Option<i64> {
        let data = self.session.lock().unwrap();
        match data.get(k) {
            None => None,
            Some(u) => Some(*u)
        }
    }

    fn delete(&mut self, k: &str) -> Option<i64> {
        let mut data = self.session.lock().unwrap();
        data.remove(k)
    }

    fn clear_expired(&mut self) {
        let mut data = self.session.lock().unwrap();
        let now_millis: i64 = Local::now().timestamp_millis();
        let expired_interval = 1000 * 60 * 30;
        let mut expired_keys = Vec::<String>::new();
        for (k, v) in data.iter() {
            if now_millis - v > expired_interval {
                expired_keys.push(k.to_string());
            }
        }
        for k in expired_keys {
            data.remove(k.as_str());
        }
    }

}